package com.lujieni.springbootmybatis.permission.rule;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.lujieni.springbootmybatis.po.BasicEntity;
import com.lujieni.springbootmybatis.util.CollectionUtils;
import com.lujieni.springbootmybatis.util.MyBatisUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @Author：Jie Ni
 * @Date: 2025/10/27 9:47
 * @Description:
 */
@Slf4j
public class CommonPermissionRule implements DataPermissionRule {

    private static final Set<String> TABLE_NAME_SET = new HashSet<>();

    private static final ConcurrentHashMap<String, String> TABLE_FIELD_MAP = new ConcurrentHashMap<>();

    private static List<Long> dataIdList = Arrays.asList(1L, 2L);

    public void addTableFieldMap(String tableName, String fieldName) {
        TABLE_FIELD_MAP.put(tableName, fieldName);
    }

    public void addTableName(String tableName) {
        TABLE_NAME_SET.add(tableName);
    }

    public void addDataColumn(Class<? extends BasicEntity> entityClass, String columnName) {
        String tableName = getTableName(entityClass);
        addTableName(tableName);
        addTableFieldMap(tableName, columnName);
    }

    private String getTableName(Class<? extends BasicEntity> entityClass) {
        TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
        if (tableInfo == null) {
            log.warn("从实体类({})获取数据库表信息为 null", entityClass.getSimpleName());
            return null;
        }
        return tableInfo.getTableName();
    }

    @Override
    public Set<String> getTableNames() {
        return TABLE_NAME_SET;
    }

    @Override
    public Expression getExpression(String tableName, Alias tableAlias) {
        // 如果字段映射不存在则无需拦截
        String columnName = TABLE_FIELD_MAP.get(tableName);
        if (StringUtils.isEmpty(columnName)){
            return null;
        }
        // 过滤掉 dataIds 里的 null 值，如：{"shop_id":[null]}
        dataIdList = dataIdList.stream().filter(Objects::nonNull).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(dataIdList)) {
            return null;
        }
        // 拼接条件
        if (dataIdList.size() == 1) {
            return new EqualsTo(MyBatisUtils.buildColumn(tableName, tableAlias, columnName), new LongValue(dataIdList.get(0)));
        }
        return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName),
                // Parenthesis 的目的，是提供 (1,2,3) 的 () 左右括号
                new ParenthesedExpressionList<>(new ExpressionList<>(CollectionUtils.convertList(dataIdList, LongValue::new))));
    }
}
